package com.zhihuishu.micro.course.service.impl;

import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.Pipeline;

import com.github.abel533.mapper.Mapper;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.zhihuishu.micro.course.constant.AppTipConstant;
import com.zhihuishu.micro.course.dao.UserViewLogMapper;
import com.zhihuishu.micro.course.helper.RedisKeyHelper;
import com.zhihuishu.micro.course.model.TipInfo;
import com.zhihuishu.micro.course.model.UserViewLog;
import com.zhihuishu.micro.course.service.UserViewLogService;
import com.zhihuishu.toolkit.helper.BeanHelper;
import com.zhihuishu.toolkit.jedis.JedisHelper;
import com.zhihuishu.toolkit.jedis.JedisHelper.Handler;

@Service("userViewLoggerService")
public class UserViewLogServiceImpl extends BaseServiceImpl<UserViewLog> implements UserViewLogService {

    @Resource
    private UserViewLogMapper userViewLogMapper;

   

    protected Logger logger = LoggerFactory.getLogger(getClass());

    private ThreadLocal<String> threadLocal = new ThreadLocal<String>();

    @Override
    public void saveUserViewLog(UserViewLog userViewLog) {
        final String key = JedisHelper.key("cc:courseId", userViewLog.getCourseId(), "userId",
                userViewLog.getUserId());
        if (logger.isDebugEnabled()) {
            logger.debug("查询用户修改点缓存的key为:{}", key);
        }
        final String field = String.format("%d-%d-%d", userViewLog.getModule(), userViewLog.getViewPoint(),
                userViewLog.getViewPointId());
        if (logger.isDebugEnabled()) {
            logger.debug("查询用户修改点的field为:{}", field);
        }
        jedisExecutor.execute( new Handler() {

            @Override
            public void handle(Jedis jedis) {
                String tempViewTime = jedis.hget(key, field);
                threadLocal.set(tempViewTime);
            }
        });
        String lastViewTime = threadLocal.get();// 获取最后一次模块的查看时间
        if (logger.isDebugEnabled()) {
            logger.debug("最后观看的时间为{}", lastViewTime);
        }
        final long newLastUpdatetime = System.currentTimeMillis();// 最新的观看时间
        if (logger.isDebugEnabled()) {
            logger.debug("最新的观看时间为{}", newLastUpdatetime);
        }
        userViewLog.setLastViewTime(newLastUpdatetime);
        userViewLog.setLastViewDate(new Date(newLastUpdatetime));
        if (lastViewTime == null) {// 从未观看过(缓存中没有数据)
            // 模块id-查看点-查看点id
            UserViewLog temp = userViewLogMapper.selectByPrimaryKey(userViewLog);
            if (logger.isDebugEnabled()) {
                logger.debug("查询输到数据库中用户模块点的观看记录为:{}", temp);
            }
            if (temp == null) {
                int affectCount = userViewLogMapper.insertSelective(userViewLog);
                if (logger.isDebugEnabled()) {
                    logger.debug("插入数据影响的行数:{}", affectCount);
                }
            } else {
                int affectCount = userViewLogMapper.updateByPrimaryKey(userViewLog);
                if (logger.isDebugEnabled()) {
                    logger.debug("更新数据影响的行数为:{}", affectCount);
                }
            }

        } else {
            int affectCount = userViewLogMapper.updateByPrimaryKey(userViewLog);
            if (logger.isDebugEnabled()) {
                logger.debug("更新数据影响的行数为:{}", affectCount);
            }
        }
        // 把最新的查看时间设置到缓存中
        jedisExecutor.execute( new Handler() {
            @Override
            public void handle(Jedis jedis) {
                //jedis.del(key);
                jedis.hset(key, field, newLastUpdatetime + "");

            }
        });

    }

    @Override
    public List<TipInfo> queryUserUpdatesDetial(UserViewLog userViewLog) {

        final String userReadKey = JedisHelper.key("cc:courseId", userViewLog.getCourseId(), "userId",
                userViewLog.getUserId());
        if (logger.isDebugEnabled()) {
            logger.debug("查询用户查看修改点的key为:{}", userReadKey);
        }
        final String courseChangeListKey = RedisKeyHelper.getCourseTipSetKey(userViewLog.getCourseId());
        if (logger.isDebugEnabled()) {
            logger.debug("查询到课程更改信息的列表key为:{}", courseChangeListKey);
        }
        List<TipInfo> infos = getCourseChangeInfos(courseChangeListKey);
        if (logger.isDebugEnabled()) {
            logger.debug("课程{}的更新信息为{}", userViewLog.getCourseId(), infos);
        }
        if (userViewLog.getModule() != 3) { // 查看的是其他步骤
            return getUserUnCatchTipInfosByModule(userViewLog, userReadKey, infos);

        } else {// 查看的是第三步
            Map<String, String> lastViewVideoMap = getLastViewVideoMap(userReadKey); // 查询所有跟用户观看视频记录的键值信息
            if (logger.isDebugEnabled()) {
                logger.debug("用户观看视频记录的所有键值信息为:{}", lastViewVideoMap);
            }

            Map<String, String> lessonViedoViewMap = Maps.newHashMap();// 节视频观看信息
            Map<String, String> childLessonVideoViewMap = Maps.newHashMap();// 小节视频的观看信息
            if (lastViewVideoMap != null && lastViewVideoMap.size() > 0) {
                Iterator<Entry<String, String>> iterator = lastViewVideoMap.entrySet().iterator();
                Entry<String, String> next = null;
                String videoViewKey = null;
                String[] split = null;
                while (iterator.hasNext()) {
                    next = iterator.next();
                    videoViewKey = next.getKey();
                    split = videoViewKey.split("-");
                    if (split[1].equals(AppTipConstant.LESSON_VIEW)) {// 节视频
                        lessonViedoViewMap.put(split[2], next.getValue());
                    }
                    if (split[1].equals(AppTipConstant.LESSON_VIDEO_VIEW)) {// 小节视频
                        childLessonVideoViewMap.put(split[2], next.getValue());
                    }
                }
            }
            if (logger.isDebugEnabled()) {
                logger.debug("用户观看节视频的信息的为:{}", lessonViedoViewMap);
                logger.debug("用户观看小节的视频信心为:{}", childLessonVideoViewMap);
            }
            return getUserUncacheVideoTipInfos(infos, lessonViedoViewMap, childLessonVideoViewMap,
                    userViewLog);

        }

    }

    private List<TipInfo> getUserUncacheVideoTipInfos(List<TipInfo> infos,
            Map<String, String> lessonViedoViewMap, Map<String, String> childLessonVideoViewMap,
            UserViewLog userViewLog) {
        List<TipInfo> userUncatchTipInfo = Lists.newArrayList();

        if (infos != null && !infos.isEmpty()) {
            for (TipInfo tipInfo : infos) {
                if (logger.isDebugEnabled()) {
                    logger.debug("循环的更新信息为{}", tipInfo);
                }
                if (tipInfo == null) {
                    continue;
                }
                if (logger.isDebugEnabled()) {
                    logger.debug("判断用户id是否相同userId={},tipInfoUserId={},result={}", userViewLog.getUserId(),
                            tipInfo.getUserId(), userViewLog.getUserId() == tipInfo.getUserId());
                }
                if (userViewLog.getUserId() == tipInfo.getUserId()) {
                    continue;
                }
                if (tipInfo.getChangePoint() == 6) {// 节视频
                    if (logger.isDebugEnabled()) {
                        logger.debug("节视频是否看过{}",
                                lessonViedoViewMap.containsKey(String.valueOf(tipInfo.getPointId())));
                    }
                    if (lessonViedoViewMap.containsKey(String.valueOf(tipInfo.getPointId()))) {// 表示看过
                        if (tipInfo.getLastModify() > Long.parseLong(lessonViedoViewMap.get(String
                                .valueOf(tipInfo.getPointId())))) {// 视频最后修改时间实在用户上一次看之后
                            userUncatchTipInfo.add(tipInfo);
                        }
                    } else {// 没看
                        if (logger.isDebugEnabled()) {
                            logger.debug("添加没有看过节视频更新{}", tipInfo);
                        }
                        userUncatchTipInfo.add(tipInfo);
                    }
                }
                if (tipInfo.getChangePoint() == 7) {// 小节视频
                    // 节视频
                    if (logger.isDebugEnabled()) {
                        logger.debug("小节视频是否看过{}",
                                childLessonVideoViewMap.containsKey(String.valueOf(tipInfo.getPointId())));
                    }
                    if (childLessonVideoViewMap.containsKey(String.valueOf(tipInfo.getPointId()))) {// 表示看过
                        if (tipInfo.getLastModify() > Long.parseLong(childLessonVideoViewMap.get(String
                                .valueOf(tipInfo.getPointId())))) {// 视频最后修改时间实在用户上一次看之后
                            userUncatchTipInfo.add(tipInfo);
                        }
                    } else {// 没看
                        if (logger.isDebugEnabled()) {
                            logger.debug("添加没有看过小节视频更新{}", tipInfo);
                        }
                        userUncatchTipInfo.add(tipInfo);
                    }

                }
            }
        }
        if (logger.isDebugEnabled()) {
            logger.debug("用户没有观看的更新信息为{}", userUncatchTipInfo);
        }
        return userUncatchTipInfo;
    }

    // 查询所有跟用户观看视频记录的键值信息
    private Map<String, String> getLastViewVideoMap(final String userReadKey) {
        final Map<String, String> viewMapWithVideo = Maps.newHashMap();
        jedisExecutor.execute( new Handler() {

            @Override
            public void handle(Jedis jedis) {
                Map<String, String> map = jedis.hgetAll(userReadKey);
                if (map != null && map.size() > 0) {
                    Iterator<Entry<String, String>> iterator = map.entrySet().iterator();
                    Entry<String, String> next = null;
                    String key2 = null;
                    while (iterator.hasNext()) {
                        next = iterator.next();
                        key2 = next.getKey();
                        if (key2 != null && key2.startsWith("3")) {// 第三步
                            viewMapWithVideo.put(next.getKey(), next.getValue());
                        }
                    }
                }
            }
        });
        return viewMapWithVideo;
    }

    private List<TipInfo> getUserUnCatchTipInfosByModule(UserViewLog userViewLog, final String key,
            List<TipInfo> infos) {

        List<TipInfo> userUnCatchInfos = Lists.newArrayList();// 用于保存用户没有查看到的最新的课程更新信息
        final String field = String.format("%d-0-0", userViewLog.getModule());
        if (logger.isDebugEnabled()) {
            logger.debug("查询用户查看修改点的field:{}", field);
        }
        jedisExecutor.execute( new Handler() {
            @Override
            public void handle(Jedis jedis) {
                String lastViewTime = jedis.hget(key, field);
                if (logger.isDebugEnabled()) {
                    logger.debug("查询到最后的访问时间为:{}", lastViewTime);
                }
                threadLocal.set(lastViewTime);

            }
        });

        Long tempLastView = null;// 最后查看时间
        if (threadLocal.get() == null) {// 缓存中为空
            tempLastView = 0L;// 取最小的一个时间
        } else {
            tempLastView = Long.parseLong(threadLocal.get());
        }
        if (infos != null && infos.size() > 0) {
            for (TipInfo tipInfo : infos) {
                if (tipInfo.getModule()!=userViewLog.getModule()) {//过滤模块
                    continue;
                }
                if (tipInfo.getUserId()==userViewLog.getUserId()) {// 过滤用户
                    continue;
                }
                if (tipInfo.getLastModify() > tempLastView) {// 最后修改的时间是在最后查看的时间后面
                    userUnCatchInfos.add(tipInfo);
                }
            }
        }
        if (logger.isDebugEnabled()) {
            logger.debug("获取到用户没有查看的的信息列表为:{}", userUnCatchInfos);
        }
        return userUnCatchInfos;
    }

    // 查询课程的修改记录列表
    private List<TipInfo> getCourseChangeInfos(final String courseChangeListKey) {
        final List<TipInfo> infos = Lists.newArrayList();
        jedisExecutor.execute( new Handler() {
            @Override
            public void handle(Jedis jedis) {
                Set<String> set = jedis.smembers(courseChangeListKey);
                if (logger.isDebugEnabled()) {
                    logger.debug("课程修改信息的id为", set);
                }
                if (set != null && set.size() > 0) {
                    Pipeline pipelined = jedis.pipelined();
                    for (String string : set) {
                        pipelined.hgetAll(RedisKeyHelper.getTipInfoKey(Integer.parseInt(string)));
                    }
                    List<Object> list = pipelined.syncAndReturnAll();
                    if (list != null && list.size() > 0) {
                        Map<String, String> map = null;
                        TipInfo bean = null;
                        for (Object object : list) {
                            if (object == null) {
                                continue;
                            }
                            map = (Map<String, String>) object;
                            bean = new TipInfo();
                            BeanHelper.populate(bean, map);
                            infos.add(bean);
                        }
                    }

                }

            }
        });
        return infos;
    }

    @Override
    public Map<Integer, Integer> queryUpdateCountForMainPage(long courseId, long userId) {
        final String userCourseReadKey = JedisHelper.key("cc:courseId", courseId, "userId", userId);
        if (logger.isDebugEnabled()) {
            logger.debug("查询用户修改点缓存的key为:{}", userCourseReadKey);
        }
        final String courseChangeListKey = RedisKeyHelper.getCourseTipSetKey(courseId);// 课程修改的记录表
        if (logger.isDebugEnabled()) {
            logger.debug("查询课程修改记录的key为:{}", courseChangeListKey);
        }
        List<TipInfo> courseChangeInfos = getCourseChangeInfos(courseChangeListKey);
        if (logger.isDebugEnabled()) {
            logger.debug("课程的修改记录查询到的信息为:{}", courseChangeInfos);
        }
        final String firstStepField = String.format("%d-0-0", 1);
        final String secondStepField = String.format("%d-0-0", 2);
        final String fourthStepField = String.format("%d-0-0", 4);
        final String fifthStepField = String.format("%d-0-0", 5);
        final String sixStepField = String.format("%d-0-0", 6);
        if (logger.isDebugEnabled()) {
            logger.debug("第一步的key:{}", firstStepField);
            logger.debug("第二步的key:{}", secondStepField);
            logger.debug("第四步的key:{}", fourthStepField);
            logger.debug("第五步的key:{}", fifthStepField);
            logger.debug("第六步的key:{}", sixStepField);
        }
        final Map<Integer, Long> map = Maps.newHashMap();
        jedisExecutor.execute( new Handler() {
            @Override
            public void handle(Jedis jedis) {
                List<String> list = jedis.hmget(userCourseReadKey, firstStepField, secondStepField,
                        fourthStepField, fifthStepField, sixStepField);
                if (logger.isDebugEnabled()) {
                    logger.debug("查询到的一二四五六步最后查看时间:{}", list);
                }
                map.put(1, list.get(0) == null ? 0 : Long.parseLong(list.get(0)));
                map.put(2, list.get(1) == null ? 0 : Long.parseLong(list.get(1)));
                map.put(4, list.get(2) == null ? 0 : Long.parseLong(list.get(2)));
                map.put(5, list.get(3) == null ? 0 : Long.parseLong(list.get(3)));
                map.put(6, list.get(4) == null ? 0 : Long.parseLong(list.get(4)));
                if (logger.isDebugEnabled()) {
                    logger.debug("非第三步各个步骤最后查看时间为信息为:{}", map);
                }

            }
        });
        Map<String, String> lastViewVideoMap = getLastViewVideoMap(userCourseReadKey); // 查询所有跟用户观看视频记录的键值信息
        if (logger.isDebugEnabled()) {
            logger.debug("用户观看视频记录的所有键值信息为:{}", lastViewVideoMap);
        }
        Map<String, String> lessonViedoViewMap = Maps.newHashMap();// 节视频观看信息<节id---最后查看时间>
        Map<String, String> childLessonVideoViewMap = Maps.newHashMap();// 小节视频的观看信息<小节id---最后查看时间>
        if (lastViewVideoMap != null && lastViewVideoMap.size() > 0) {
            Iterator<Entry<String, String>> iterator = lastViewVideoMap.entrySet().iterator();
            Entry<String, String> next = null;
            String videoViewKey = null;
            String[] split = null;
            while (iterator.hasNext()) {
                next = iterator.next();
                videoViewKey = next.getKey();
                split = videoViewKey.split("-");
                if (split[1].equals(AppTipConstant.LESSON_VIEW)) {// 节视频
                    lessonViedoViewMap.put(split[2], next.getValue());
                }
                if (split[1].equals(AppTipConstant.LESSON_VIDEO_VIEW)) {// 小节视频
                    childLessonVideoViewMap.put(split[2], next.getValue());
                }
            }
        }
        if (logger.isDebugEnabled()) {
            logger.debug("用户观看节视频的信息的为:{}", lessonViedoViewMap);
            logger.debug("用户观看小节的视频信息为:{}", childLessonVideoViewMap);
        }
        Map<Integer, Integer> resultMap = Maps.newHashMap();
        resultMap.put(1, 0);
        resultMap.put(2, 0);
        resultMap.put(3, 0);
        resultMap.put(4, 0);
        resultMap.put(5, 0);
        resultMap.put(6, 0);
        if (courseChangeInfos != null && !courseChangeInfos.isEmpty()) {
            for (TipInfo tipInfo : courseChangeInfos) {
                if (tipInfo == null) {
                    continue;
                }
                if (tipInfo.getModule() != 3) {// 非第三步
                    if (tipInfo.getUserId() == userId) {//
                        continue;
                    }
                    if (tipInfo.getLastModify() > map.get(tipInfo.getModule())) {
                        resultMap.put(tipInfo.getModule(), resultMap.get(tipInfo.getModule()) + 1);
                    }
                } else {
                    if (tipInfo.getUserId() == userId) {// 排除自己更新的信息
                        continue;
                    }
                    if (tipInfo.getChangePoint() == 6) {// 节
                        if (logger.isDebugEnabled()) {
                            logger.debug("是否包含该节修改点:{},result={}",tipInfo.getPointId(),lessonViedoViewMap.containsKey(String.valueOf(tipInfo.getPointId())));
                        }
                        if (lessonViedoViewMap.containsKey(String.valueOf(tipInfo.getPointId()))) {
                            if (tipInfo.getLastModify() > Long.parseLong(lessonViedoViewMap.get(String.valueOf(tipInfo.getPointId())))) {// 节最后修改时间大于最后观看时间
                                resultMap.put(tipInfo.getModule(), resultMap.get(tipInfo.getModule()) + 1);
                            }
                        } else {// 节没有看过
                            resultMap.put(tipInfo.getModule(), resultMap.get(tipInfo.getModule()) + 1);
                        }
                    }
                    if (tipInfo.getChangePoint() == 7) {// 小节
                        if (logger.isDebugEnabled()) {
                            logger.debug("是否包含该小节修改点:{},result={}",tipInfo.getPointId(),childLessonVideoViewMap.containsKey(String.valueOf(tipInfo.getPointId())));
                        }
                        if (childLessonVideoViewMap.containsKey(String.valueOf(tipInfo.getPointId()))) {
                            if (tipInfo.getLastModify() > Long.parseLong(childLessonVideoViewMap.get(String.valueOf(tipInfo.getPointId())))) {// 小节最后修改时间大于观看时间
                                resultMap.put(tipInfo.getModule(), resultMap.get(tipInfo.getModule()) + 1);
                            }
                        } else {// 小节没有看过
                            resultMap.put(tipInfo.getModule(), resultMap.get(tipInfo.getModule()) + 1);
                        }

                       
                    }
                }

            }
        }

        return resultMap;
    }

    @Override
    public Mapper<UserViewLog> getMapper() {
        
        return userViewLogMapper;
    }

}
